package cn.hinglo.baseservice.config;

import cn.hinglo.common.entity.Result;
import cn.hinglo.common.enums.ExceptionEnum;
import cn.hinglo.common.exception.ResultException;
import cn.hinglo.common.utils.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.ServletException;
import javax.validation.ValidationException;


/**
 * @author HingLo
 * @createTime: 2018/1/4
 * @description: 统一异常处理类
 */
@ControllerAdvice
@Slf4j
public class ExceptionConfig {

    private Integer code;

    private String message;

    /***
     * 全局异常处理器
     *
     * @param e 捕获的异常
     * @return 返回异常处理结果
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result handle(Exception e) {
        if (e instanceof ResultException) {
            ResultException resultException = (ResultException) e;
            setCodeAndMessage(resultException.getCode(), resultException.getMessage());
            log.info("自定义的异常:{}", e.getMessage());
        } else if (e instanceof DataAccessException) {
            // 数据库操作异常
            setCodeAndMessage(ExceptionEnum.DATABASEERROR);
            log.info("数据库异常：{}", e.getMessage());
        } else if (e instanceof NoHandlerFoundException) {
            setCodeAndMessage(ExceptionEnum.NOT404);
            log.info("URL Not Find ：{}", e.getMessage());
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            setCodeAndMessage(ExceptionEnum.NOT405);
            log.info("request method not supported：{}", e.getMessage());
        } else if (e instanceof ValidationException) {
            // 此方法是参数校验没有通过抛出的全局异常处理
            setCodeAndMessage(ExceptionEnum.VIOLATIONERROR, e.getMessage());
            log.info("参数校验异常：{}", e.getMessage());
        } else if (e instanceof MethodArgumentTypeMismatchException) {
            // 参数注入异常的,比如应该需要数字,而是给了字符串
            setCodeAndMessage(ExceptionEnum.PARAMERROR, e.getMessage());
            log.info("参数注入异常：{}", e.getMessage());
        } else if (e instanceof MissingServletRequestParameterException) {
            // 参数绑定异常,缺少必传参数
            setCodeAndMessage(ExceptionEnum.NEEDPARAM, e.getMessage());
            log.info("参数注入异常：{}", e.getMessage());
        } else if (e instanceof ServletException) {
            // 服务器异常
            setCodeAndMessage(ExceptionEnum.SERVLETERROR);
            log.info("服务器异常：{}", e.getMessage());
        } else {
            // 程序运行过程中,遇到的不知到的异常
            setCodeAndMessage(ExceptionEnum.ORTHERERROR);
            log.info("其他类型的异常：{}", e.getMessage());
        }
        e.printStackTrace();
        log.info(".......................异常捕获结束............................");
        return ResultUtils.error(code, message);
    }

    /***
     * 自定义异常返回信息
     *
     * @param code 异常码
     * @param message 异常信息
     */
    private void setCodeAndMessage(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    /**
     * 通过枚举异常错误信息
     *
     * @param exceptionEnum 枚举异常错误对象
     */
    private void setCodeAndMessage(ExceptionEnum exceptionEnum) {
        this.code = exceptionEnum.getCode();
        this.message = exceptionEnum.getMessage();
    }

    /**
     * 构造携带了额外的错误信息的异常信息
     *
     * @param exceptionEnum 枚举类型
     * @param extra         额外消息
     */
    private void setCodeAndMessage(ExceptionEnum exceptionEnum, String extra) {
        this.code = exceptionEnum.getCode();
        this.message = exceptionEnum.getMessage() + "  ========>>" + extra;
    }

}
